const path = require("path");
const os = require("os");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin");
const { PurgeCSSPlugin } = require("purgecss-webpack-plugin");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");

const isProduction = process.env.NODE_ENV === 'production'
const threads = os.cpus().length / 2

function handleStyle(loader, isModule) {
  return [
    isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: ['postcss-preset-env']
        }
      }
    },
    loader
  ].filter(Boolean)
}

module.exports = {
  mode: isProduction ? 'production' : 'development',
  entry: {
    main: "./src/main.js",
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: 'js/[name]-[contenthash:8].js',
    chunkFilename: 'js/[name]-chunk[contenthash:8].js',
    assetModuleFilename: 'public/[name]-[hash:8][ext][query]',
    clean: true,
  },
  devtool: isProduction ? false : 'eval-cheap-module-source-map',
  cache: {
    type: "filesystem",
  },
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.(js|jsx)$/,
            include: path.resolve(__dirname, 'src'),
            use: [
              {
                loader: 'thread-loader',
                options: {
                  works: threads
                }
              },
              'babel-loader',
            ]
          },
          {
            test: /\.css$/,
            include: path.resolve(__dirname, 'src'),
            use: handleStyle(),
            generator: {
              filename: 'css/[name].[contenthash:8].css'
            }
          },
          {
            test: /\.less$/,
            include: path.resolve(__dirname, 'src'),
            use: handleStyle('less-loader'),
            generator: {
              filename: 'css/[name].[contenthash:8].css'
            }
          },
          {
            test: /\.(png|jpeg|jpg|svg)$/,
            exclude: path.resolve(__dirname, 'public'),
            type: 'asset',
            parser: {
              dataUrlCondition: {
                maxSize: 10 * 1024
              }
            },
            generator: {
              filename: "public/image/[name][hash:8][ext]"
            }
          },
          {
            test: /\.(ttf|woff2?)$/,
            exclude: path.resolve(__dirname, 'public'),
            type: 'asset',
            parser: {
              dataUrlCondition: {
                maxSize: 20 * 1024
              }
            },
            generator: {
              filename: 'public/fonts/[name][hash:8][ext]'
            }
          },
        ]
      }
    ]
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        react: {
          test: /[\\/]node_modules[\\/]react(.*)?/,
          name: 'chunk-react'
        }
      }
    },
    minimizer: [
      new TerserPlugin({
        parallel: threads
      }),
      new CssMinimizerWebpackPlugin(),
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              ["gifsicle", { interlaced: true }],
              ["jpegtran", { progressive: true }],
              ["optipng", { optimizationLevel: 5 }],
              [
                "svgo",
                {
                  plugins: [
                    {
                      name: "preset-default",
                      params: {
                        overrides: {
                          removeViewBox: false,
                          addAttributesToSVGElement: {
                            params: {
                              attributes: [
                                { xmlns: "http://www.w3.org/2000/svg" },
                              ],
                            },
                          },
                        },
                      },
                    },
                  ],
                },
              ],
            ],
          },
        },
      }),
    ],
    runtimeChunk: true
  },
  plugins: [
    process.env.ANALYZER && new BundleAnalyzerPlugin(),
    new ESLintWebpackPlugin({
      extensions: ['js', 'jsx'],
      context: path.resolve(__dirname, "./src"),
      cache: true,
      failOnError: true,
      threads
    }),
    new HtmlWebpackPlugin({ template: "./public/index.html" }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:8].css',
      chunkFilename: 'css/[name].chunk[contenthash:8].css'
    }),
    new CopyPlugin({
      patterns: [{
        from: './public',
        to: path.resolve(__dirname, 'dist'),
        globOptions: {
          ignore: ['**/index.html']
        }
      }]
    }),
  ].filter(Boolean),
  resolve: {
    extensions: ['.jsx', '.js', '.json', '.css'],
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  },
  devServer: {
    host: 'localhost',
    port: 9090,
    open: true,
    hot: true,
    historyApiFallback: true
  }
};
